import bcrypt from 'bcryptjs';
import { DataTypes } from 'sequelize';
import BaseModel from './BaseModel.js';
import logger from '../config/logger.js';

// 用户角色
const ROLES = {
  ADMIN: 'admin',
  TEACHER: 'teacher',
  STUDENT: 'student',
};

class User extends BaseModel {
  static initModel(sequelize) {
    const attributes = {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      username: {
        type: DataTypes.STRING(50),
        allowNull: false,
        unique: true,
        validate: {
          len: [3, 50],
        },
      },
      password: {
        type: DataTypes.STRING(100),
        allowNull: false,
        validate: {
          len: [6, 100],
        },
      },
      name: {
        type: DataTypes.STRING(50),
        allowNull: false,
      },
      email: {
        type: DataTypes.STRING(100),
        allowNull: false,
        unique: true,
        validate: {
          isEmail: true,
        },
      },
      phone: {
        type: DataTypes.STRING(20),
        allowNull: true,
      },
      role: {
        type: DataTypes.TEXT,
        defaultValue: ROLES.STUDENT,
        allowNull: false,
        validate: {
          isIn: [Object.values(ROLES)]
        }
      },
      isActive: {
        type: DataTypes.BOOLEAN,
        defaultValue: true,
        field: 'is_active',
      },
      lastLogin: {
        type: DataTypes.DATE,
        field: 'last_login',
      },
      passwordChangedAt: {
        type: DataTypes.DATE,
        field: 'password_changed_at',
      },
      passwordResetToken: {
        type: DataTypes.STRING,
        field: 'password_reset_token',
      },
      passwordResetExpires: {
        type: DataTypes.DATE,
        field: 'password_reset_expires',
      },
    };

    const options = {
      hooks: {
        beforeCreate: async (user) => {
          if (user.password) {
            user.password = await bcrypt.hash(user.password, 12);
          }
        },
        beforeUpdate: async (user) => {
          if (user.changed('password')) {
            user.password = await bcrypt.hash(user.password, 12);
            user.passwordChangedAt = Date.now() - 1000; // 确保令牌在密码更改后失效
          }
        },
      },
    };

    const UserModel = super.init(sequelize, 'User', attributes, options);

    // 添加实例方法
    UserModel.prototype.validatePassword = async function(candidatePassword, userPassword) {
      return await bcrypt.compare(candidatePassword, userPassword);
    };

    UserModel.prototype.changedPasswordAfter = function(JWTTimestamp) {
      if (this.passwordChangedAt) {
        const changedTimestamp = parseInt(
          this.passwordChangedAt.getTime() / 1000,
          10
        );
        return JWTTimestamp < changedTimestamp;
      }
      return false;
    };

    UserModel.prototype.createPasswordResetToken = function() {
      const resetToken = require('crypto').randomBytes(32).toString('hex');
      this.passwordResetToken = require('crypto')
        .createHash('sha256')
        .update(resetToken)
        .digest('hex');

      this.passwordResetExpires = Date.now() + 10 * 60 * 1000; // 10分钟后过期
      return resetToken;
    };

    UserModel.prototype.toJSON = function() {
      const values = Object.assign({}, this.get());
      delete values.password;
      delete values.passwordResetToken;
      delete values.passwordResetExpires;
      return values;
    };

    // 添加静态属性
    UserModel.ROLES = ROLES;

    return UserModel;
  }

  // 定义关联关系
  static associate(models) {
    // 教师教授的课程
    this.hasMany(models.Course, {
      foreignKey: 'teacherId',
      as: 'teachingCourses',
    });

    // 学生的选课记录
    this.hasMany(models.Enrollment, {
      foreignKey: 'studentId',
      as: 'enrollments',
    });
  }
}

export default User;
